package com.molichuxing.gateway.bff.order.services.impl;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseCodeEnum;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.DingTalkUtil;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.order.convertor.Convert;
import com.molichuxing.gateway.bff.order.entity.request.create.PaymentOfflineCreateVo;
import com.molichuxing.gateway.bff.order.entity.request.create.PaymentOfflineScheduleCreateVo;
import com.molichuxing.gateway.bff.order.entity.response.*;
import com.molichuxing.gateway.bff.order.services.OrderScheduleBffService;
import com.molichuxing.gateway.property.EmailSubjectEnum;
import com.molichuxing.gateway.property.EmailTemplateEnum;
import com.molichuxing.gateway.utils.TokenUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.request.create.OfflineBizCreateDto;
import com.molichuxing.services.business.dto.request.create.OfflineOrdersBizCreateDto;
import com.molichuxing.services.business.dto.response.*;
import com.molichuxing.services.business.service.OfflineBizService;
import com.molichuxing.services.business.service.OrderScheduleBizService;
import com.molichuxing.services.business.service.VehicleBizService;
import com.molichuxing.services.infrastructure.dto.request.create.OrderStatusFlowCreateDto;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.dto.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单排期相关bff
 * 
 * @author zoumingyu
 * @date 2019年8月23日
 *
 */
@Service("orderScheduleBffService")
public class OrderScheduleBffServiceImpl implements OrderScheduleBffService {
	private static final Logger logger = LoggerFactory.getLogger(OrderScheduleBffServiceImpl.class);


	@Value("${email_account}")
	private String EMAIL_ACCOUNT;

	@Value("${email_password}")
	private String EMAIL_PASSWORD;

	@Value("${order.repayment.check.url}")
	private String ORDER_REPAYMENT_CHECK_URL;

	@Resource
	private OrderScheduleService orderScheduleService;

	@Resource
	private OrderExclusivelService orderExclusivelService;

	@Resource
	private OrderScheduleBizService orderScheduleBizService;

	@Resource
	private OrderService orderService;

	@Resource
	private UserService userService;

    @Resource
    private CarService carService;

    @Resource
    private VehicleBizService vehicleBizService;

    @Resource
    private DealerService dealerService;

    @Resource
    private OfflineOrdersService offlineOrdersService;

    @Resource
    private DealerDetailService dealerDetailService;

    @Resource
    private OfflineService offlineService;

    @Resource
    private OfflineBizService offlineBizService;

    @Resource
    private OrderDealerService orderDealerService;

    @Resource
    private OrderStatusFlowService orderStatusFlowService;

    @Resource
    private OrderRenegeService orderRenegeService;

    @Resource
    private LawsuitService lawsuitService;

    @Resource
    private TokenUtil tokenUtil;

    @Resource
    private RiskEmailService riskEmailService;

    /**
     * 分页获取专属里程订单还款计划信息
     *
     * @param params   orderCode：订单号-long <br />
     *                 userRealName：用户姓名-string <br />
     *                 userPhone：用户手机号-string <br />
     * @param pageNum  页数
     * @param pageSize 每页条数
     * @return
     * @throws Exception
     */
    @Override
    public Paged<OrderRepaymentVo> getExclusivelOrderCurrentPeriod(Map<String, Object> params, int pageNum,
                                                                   int pageSize) throws Exception {
        Paged<OrderRepaymentVo> result = new Paged<>(new ArrayList<>(), 0, pageSize);
        ;
        // 判断查询条件是否有用户信息
        if (StringUtils.isNotBlank(ObjectCastUtil.castString(params.get("userRealName")))
                || StringUtils.isNotBlank(ObjectCastUtil.castString(params.get("userPhone")))) {
            // 查询用户ids
            List<Integer> userIdList = getUserIds(ObjectCastUtil.castString(params.get("userRealName")),
                    ObjectCastUtil.castString(params.get("userPhone")));
            if (userIdList == null || userIdList.size() <= 0) {
                // 用户不存在
                return result;
            }
            params.put("userIds", userIdList);
            params.remove("userRealName");
            params.remove("userPhone");
            logger.info("[getExclusivelOrderCurrentPeriod]分页获取专属里程订单还款计划信息userIds：" + userIdList);
        }

		Paged<OrderScheduleCurrentPeriodDto> orderScheduleCurrentPeriodDtoPage = orderScheduleService
				.getExclusivelOrderCurrentPeriod(params, pageNum, pageSize);
		// 判断是否查询为空
		if (orderScheduleCurrentPeriodDtoPage == null) {
			return result;
		} else if (orderScheduleCurrentPeriodDtoPage.isEmpty()) {
			return result.setTotal(orderScheduleCurrentPeriodDtoPage.getTotal());
		}
	
		result.setTotal(orderScheduleCurrentPeriodDtoPage.getTotal());
		// 用户id集合
		List<Integer> userIds = new ArrayList<>();
		for (OrderScheduleCurrentPeriodDto orderScheduleCurrentPeriodDto : orderScheduleCurrentPeriodDtoPage
				.getList()) {
			userIds.add(orderScheduleCurrentPeriodDto.getUserId());
			result.getList().add(Convert.toOrderRepaymentVo(orderScheduleCurrentPeriodDto));
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);

		for (OrderRepaymentVo orderRepaymentVo : result.getList()) {
			// 用户
			UserDto userDto = userMap == null ? null
					: userMap.isEmpty() ? null : userMap.get(orderRepaymentVo.getUserId());
			// 用户手机号
			orderRepaymentVo.setUserPhone(userDto == null ? null : userDto.getPhone());
			// 用户姓名
			orderRepaymentVo.setUserRealName(userDto == null ? null : userDto.getRealName());
		}


		return result;
	}

	/**
	 * 分页获取专属里程订单逾期管理
	 * 
	 * @param params
	 *            orderCode：订单号-long <br />
	 *            userRealName：用户姓名-string <br />
	 *            userPhone：用户手机号-string <br />
	 * @param pageNum
	 *            页数
	 * @param pageSize
	 *            每页条数
	 * @return
	 * @throws Exception
	 */
	@Override
	public Paged<OrderOverdueVo> getExclusivelOrderOverdue(Map<String, Object> params, int pageNum, int pageSize)
			throws Exception {
        Paged<OrderOverdueVo> result = new Paged<>(new ArrayList<>(), 0, pageSize);
        // 查询tab页签数量
        result.setTab(getOverdueTab());
        // 判断查询条件是否有用户信息
        if (StringUtils.isNotBlank(ObjectCastUtil.castString(params.get("userRealName")))
                || StringUtils.isNotBlank(ObjectCastUtil.castString(params.get("userPhone")))) {
	        // 查询用户ids
	        List<Integer> userIdList = getUserIds(ObjectCastUtil.castString(params.get("userRealName")),
			        ObjectCastUtil.castString(params.get("userPhone")));
	        if (userIdList == null || userIdList.size() <= 0) {
		        // 用户不存在
		        return result;
	        }
	        params.put("userIds", userIdList);
	        params.remove("userRealName");
	        params.remove("userPhone");
	        logger.info("[getExclusivelOrderOverdue]分页获取专属里程订单逾期管理userIds：" + userIdList);
        }

		Paged<OrderScheduleOverdueDto> orderScheduleOverdueDtoPage = orderScheduleService
				.getExclusivelOrderOverdue(params, pageNum, pageSize);
		// 判断是否查询为空
		if (orderScheduleOverdueDtoPage == null) {
			return result;
		} else if (orderScheduleOverdueDtoPage.isEmpty()) {
			return result.setTotal(orderScheduleOverdueDtoPage.getTotal());
		}

		result.setTotal(orderScheduleOverdueDtoPage.getTotal());
		// 用户id集合
		List<Integer> userIds = new ArrayList<>();
		List<Long> orderCodes = new ArrayList<>();
		for (OrderScheduleOverdueDto orderScheduleOverdueDto : orderScheduleOverdueDtoPage.getList()) {
			userIds.add(orderScheduleOverdueDto.getUserId());
			orderCodes.add(orderScheduleOverdueDto.getOrderCode());
			result.getList().add(Convert.toOrderOverdueVo(orderScheduleOverdueDto));
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);

		Map<Long, OrderExclusivelDto> orderMap = orderExclusivelService.getOrderExclusivel(orderCodes);

		for (OrderOverdueVo orderOverdueVo : result.getList()) {
			// 用户
			UserDto userDto = userMap == null ? null
					: userMap.isEmpty() ? null : userMap.get(orderOverdueVo.getUserId());
			// 用户手机号
			orderOverdueVo.setUserPhone(userDto == null ? null : userDto.getPhone());
			// 用户姓名
			orderOverdueVo.setUserRealName(userDto == null ? null : userDto.getRealName());

			OrderExclusivelDto exclusivelDto = orderMap == null ? null : orderMap.get(orderOverdueVo.getOrderCode());
			if (exclusivelDto != null) {
				orderOverdueVo.setOrderStatus(exclusivelDto.getOrderStatus().getValue());
				orderOverdueVo.setOrderStatusStr(exclusivelDto.getOrderStatus().getName());
				orderOverdueVo.setIsRenege(OrderExclusivelStatusEnum.RENEGE_ACCEPTED.getValue()
						<= exclusivelDto.getOrderStatus().getValue());
			}
		}

		return result;
	}

    private List<TabDto> getOverdueTab() throws Exception {
        List<TabDto> tabs = new ArrayList<>();
        // 逾期未还数量
        tabs.add(new TabDto("逾期未还款", 1,
                orderScheduleService.getOverdueTotal(OrderTypeEnum.EXCLUSIVEL)));
        // 协商退租数量
        tabs.add(new TabDto("逾期协商退租", 2,
                orderRenegeService.getRenegeTotal(OrderRenegeTypeEnum.NEGOTIATE)));
        // 法务诉讼数量
        tabs.add(new TabDto("法务诉讼", 3, lawsuitService.getLawsuitTotal()));
        return tabs;
    }


    /**
     * 根据用户姓名和手机号查询用户ids
     *
     * @param userRealName 用户姓名
     * @param userPhone    用户手机号
     * @return
     */
    private List<Integer> getUserIds(String userRealName, String userPhone) {
        List<Integer> result = null;
        // 查询用信息
        List<UserDto> userDtoList = userService.getUserList(null, userRealName, userPhone);
        if (userDtoList == null || userDtoList.isEmpty()) {
            // 用户不存在
            return result;
        }
        result = new ArrayList<>();
        for (UserDto userDto : userDtoList) {
            result.add(userDto.getId());
        }

        return result;
    }

    /**
     * 查询还款计划明细
     *
     * @param orderCode 订单号
     * @param overdue   是否只查询已逾期
     * @return
     */
    @Override
    public List<OrderRepaymentDetailVo> getRepaymentDetail(Long orderCode, boolean overdue) {
        List<OrderRepaymentDetailVo> result = null;

        List<OrderScheduleDto> orderScheduleDtoList = orderScheduleService.getOrderSchedule(orderCode);
		if (orderScheduleDtoList == null || orderScheduleDtoList.isEmpty()) {
			return result;
		}
		// 查询专属里程订单信息
		OrderExclusivelDto orderExclusivelDto = orderExclusivelService.getOrderExclusivel(orderCode);
		if (orderExclusivelDto == null) {
			return result;
		}
		result = new ArrayList<>();

		if (overdue) {
			LocalDateTime nowTime = LocalDateTime.now();
			for (OrderScheduleDto orderScheduleDto : orderScheduleDtoList) {
				long overdueDay = DateUtil.getDaysDiff(orderScheduleDto.getPayableDate(),
						nowTime);
				if (OrderScheduleStatusEnum.NO.equals(orderScheduleDto.getStatus()) && overdueDay > 0L) {
					// 为还款且已逾期
					OrderRepaymentDetailVo orderRepaymentDetailVo = Convert.toOrderRepaymentDetailVo(orderScheduleDto);
					orderRepaymentDetailVo.setPeriodsStr(orderScheduleDto.getPeriods() + "期");

					result.add(orderRepaymentDetailVo);
				}
			}
		} else {
			OrderRepaymentDetailVo firstTermsVo = null;
			for (OrderScheduleDto orderScheduleDto : orderScheduleDtoList) {
				// 统计首付信息
				if (orderScheduleDto.getPeriods() <= orderExclusivelDto.getFirstTerms()) {
					if (orderScheduleDto.getPeriods() == 1) {
						firstTermsVo = Convert.toOrderRepaymentDetailVo(orderScheduleDto);
						// firstTermsVo.setPeriodsStr("首付(" +
						// orderExclusivelDto.getFirstTerms() + "期)");
					} else {
						// 还款金额
						firstTermsVo.setPayable(firstTermsVo.getPayable().add(orderScheduleDto.getPayable()));
					}
					continue;
				}
				OrderRepaymentDetailVo orderRepaymentDetailVo = Convert.toOrderRepaymentDetailVo(orderScheduleDto);
				result.add(orderRepaymentDetailVo);
			}
			// 添加首付信息到返回结果
			result.add(0, firstTermsVo);
		}

		return result;
	}

	@Override
	public Paged<OrderScheduleCurrentPeriodVo> getOrderScheduleCurrentPeriodList(Map<String, Object> params, Integer pageNum, Integer pageSize) throws Exception {

		if(null !=params.get("dealerName")){
			List<Integer> dealerIds = new ArrayList<>();
			List<DealerDto> dealerDtoList = dealerService.getAllDealerListByName(String.valueOf(params.get("dealerName")));
			if(null != dealerDtoList  && dealerDtoList.size()> 0){
				for (DealerDto dealerDto:dealerDtoList) {
					dealerIds.add(dealerDto.getDealerId());
				}
			}else{
				dealerIds.add(0);
			}
			params.put("dealerIds",dealerIds);
		}
		Paged<OrderScheduleCurrentPeriodVo> currentPeriodVoPage =  new Paged<>(null, 0, pageSize);
		Paged<OrderScheduleCurrentPeriodBizDto> currentPeriodBizDtoPage = orderScheduleBizService.getOrderScheduleCurrentPeriodList(params, pageNum, pageSize);
		if (null == currentPeriodBizDtoPage) {
			currentPeriodVoPage.setTab(getRepaymentTab());
			return currentPeriodVoPage;
		}
		currentPeriodVoPage = new Paged<>();
		BeanUtils.copyProperties(currentPeriodBizDtoPage, currentPeriodVoPage);
		List<OrderScheduleCurrentPeriodVo> currentPeriodVoList = new ArrayList<>();
		OrderScheduleCurrentPeriodVo currentPeriodVo = null;
		List<OrderDealerCarVo> carInfoList = null;
		String vehicleName;
		for (OrderScheduleCurrentPeriodBizDto currentPeriodBizDto : currentPeriodBizDtoPage.getList()) {
			currentPeriodVo = new OrderScheduleCurrentPeriodVo();
			BeanUtils.copyProperties(currentPeriodBizDto, currentPeriodVo);
			currentPeriodVo.setStatusName(currentPeriodBizDto.getStatus().getName());
			// 通过经销商id查询经销商名字 入参：经销商id  出参：经销商名称
			DealerDto dealerDto = dealerService.getDealerById(currentPeriodBizDto.getDealerId());
			if(null == dealerDto){
				throw new Exception("经销商名称为空");
			}
			currentPeriodVo.setDealerName(dealerDto.getShortName());
			//查询车辆信息
			carInfoList =new ArrayList<>();
			OrderDealerCarVo orderDealerCarVo = null;
			for (Integer carId:currentPeriodVo.getCarIdList()) {
				orderDealerCarVo = new OrderDealerCarVo();
				//获取车辆基础信息
				CarDto carDto = carService.getCarById(carId);
				if(null == carDto){
					throw new Exception("车辆基础信息为空");
				}
				//获取车型名称
				vehicleName = vehicleBizService.getVehicleName(carDto.getVehicleId());
				if(null == vehicleName){
					throw new Exception("车型名称为空");
				}
				orderDealerCarVo.setLicencePlate(carDto.getLicencePlate());
				orderDealerCarVo.setVin(carDto.getVin());
				orderDealerCarVo.setVehicleName(vehicleName);
				carInfoList.add(orderDealerCarVo);
			}
			currentPeriodVo.setCarInfoList(carInfoList);
			currentPeriodVoList.add(currentPeriodVo);
		}
		currentPeriodVoPage.setList(currentPeriodVoList);
		currentPeriodVoPage.setTab(getRepaymentTab());
		return currentPeriodVoPage;
	}

	@Override
	public Paged<OrderScheduleOverdueVo> getOrderScheduleOverdueList(Map<String, Object> params, Integer pageNum, Integer pageSize) throws Exception {
		if(null !=params.get("dealerName")){
			List<Integer> dealerIds = new ArrayList<>();
			List<DealerDto> dealerDtoList = dealerService.getAllDealerListByName(String.valueOf(params.get("dealerName")));
			if(null != dealerDtoList  && dealerDtoList.size()> 0){
				for (DealerDto dealerDto:dealerDtoList) {
					dealerIds.add(dealerDto.getDealerId());
				}
			}else{
				dealerIds.add(0);
			}
			params.put("dealerIds",dealerIds);
		}
		Paged<OrderScheduleOverdueVo> overdueVoPage =  new Paged<>(null, 0, pageSize);
		Paged<OrderScheduleOverdueBizDto> overdueBizDtoPage = orderScheduleBizService.getOrderScheduleOverdueList(params, pageNum, pageSize);
		if (null == overdueBizDtoPage) {
			overdueVoPage.setTab(getRepaymentTab());
			return overdueVoPage;
		}
		overdueVoPage = new Paged<>();
		BeanUtils.copyProperties(overdueBizDtoPage, overdueVoPage);
		List<OrderScheduleOverdueVo> overdueVoList = new ArrayList<>();
		OrderScheduleOverdueVo overdueVo = null;
		List<OrderDealerCarVo> carInfoList = null;
		String vehicleName;
		for (OrderScheduleOverdueBizDto overdueBizDto : overdueBizDtoPage.getList()) {
			overdueVo = new OrderScheduleOverdueVo();
			BeanUtils.copyProperties(overdueBizDto, overdueVo);
			overdueVo.setStatusName(overdueBizDto.getStatus().getName());
			// 通过经销商id查询经销商名字 入参：经销商id  出参：经销商名称
			DealerDto dealerDto = dealerService.getDealerById(overdueBizDto.getDealerId());
			if(null == dealerDto){
				throw new Exception("经销商名称为空");
			}
			overdueVo.setDealerName(dealerDto.getShortName());
			//查询车辆信息
			carInfoList =new ArrayList<>();
			OrderDealerCarVo orderDealerCarVo = null;
			for (Integer carId:overdueVo.getCarIdList()) {
				orderDealerCarVo = new OrderDealerCarVo();
				//获取车辆基础信息
				CarDto carDto = carService.getCarById(carId);
				if(null == carDto){
					throw new Exception("车辆基础信息为空");
				}
				//获取车型名称
				vehicleName = vehicleBizService.getVehicleName(carDto.getVehicleId());
				if(null == vehicleName){
					throw new Exception("车型名称为空");
				}
				orderDealerCarVo.setLicencePlate(carDto.getLicencePlate());
				orderDealerCarVo.setVin(carDto.getVin());
				orderDealerCarVo.setVehicleName(vehicleName);
				carInfoList.add(orderDealerCarVo);
			}
			overdueVo.setCarInfoList(carInfoList);
			overdueVoList.add(overdueVo);
		}
		overdueVoPage.setList(overdueVoList);
		overdueVoPage.setTab(getRepaymentTab());
		return overdueVoPage;
	}

	/**
	 * 获取线下支付信息
	 * 
	 * @param selectParams
	 * @param pageNum
	 *            页数
	 * @param pageSize
	 *            每页条数
	 * @return
	 * @throws Exception
	 */
	@Override
	public Paged<PaymentOfflineVo> getPaymentOfflinePage(Map<String, Object> selectParams, Integer pageNum, Integer pageSize)
			throws Exception {
		if(null !=selectParams.get("dealerName")){
			List<Integer> dealerIds = new ArrayList<>();
			List<DealerDto> dealerDtoList = dealerService.getAllDealerListByName(String.valueOf(selectParams.get("dealerName")));
			if(null != dealerDtoList  && dealerDtoList.size()> 0){
				for (DealerDto dealerDto:dealerDtoList) {
					dealerIds.add(dealerDto.getDealerId());
				}
			}else{
				dealerIds.add(0);
			}
			selectParams.put("dealerIds",dealerIds);
		}
		Paged<PaymentOfflineVo> result = new Paged<>(null, 0, pageSize);
		OfflineRepayTypeEnum repayType = ObjectCastUtil.castEmun(selectParams.get("repayType"),
				OfflineRepayTypeEnum.class);
		// 查询tab
		if (OfflineRepayTypeEnum.DEALER.equals(repayType)) {
			// 经销商
			result.setTab(getRepaymentTab());
		} else if (OfflineRepayTypeEnum.USER.equals(repayType)) {
			// 用户
			result.setTab(offlineService.getMemberTabsStatistics());
		}

		// 查询列表信息
		selectParams.put("repayType", repayType.getValue());
		// 开始时间-LocalDateTime
		selectParams.put("startApplyTime", ObjectCastUtil.castLocalDateTimeStart(selectParams.get("startApplyTime")));
		// 结束时间-LocalDateTime
		selectParams.put("endApplyTime", ObjectCastUtil.castLocalDateTimeEnd(selectParams.get("endApplyTime")));

		Paged<OfflineDto> offlineDtoPage = offlineService.getOfflinePage(selectParams, pageNum, pageSize);
		if (offlineDtoPage == null) {
			return result;
		}
		List<PaymentOfflineVo> offlineVoList = new ArrayList<>();
		for (OfflineDto offlineDto : offlineDtoPage.getList()) {
			PaymentOfflineVo offlineVo = new PaymentOfflineVo();
			BeanUtils.copyProperties(offlineDto, offlineVo);
			if (offlineDto.getDealerId() != null) {
				// 获取经销商名称
				DealerDto dealerDto = dealerService.getDealerById(offlineDto.getDealerId());
				if (null == dealerDto) {
					throw new Exception("经销商信息为空");
				}
				offlineVo.setDealerName(dealerDto.getShortName());
			}
			offlineVo.setAuditStatusName(OfflineAuditStatusEnum.getName(offlineDto.getAuditStatus()));
			offlineVoList.add(offlineVo);
		}

		result.setList(offlineVoList);
		result.setPages(offlineDtoPage.getPages());
		result.setTotal(offlineDtoPage.getTotal());
		result.setPageSize(pageSize);
		result.setPageNum(pageNum);
		return result;
	}

	/**
	 * 商家-还款管理tab
	 * 
	 * @return
	 */
	private List<TabDto> getRepaymentTab() {
		List<TabDto> tabList = new ArrayList<>();
		TabDto tab = null;
		for (OrderDealerRepaymentEnum repaymentEnum : OrderDealerRepaymentEnum.values()) {
			tab = new TabDto();
			switch (repaymentEnum.getValue()) {
			case 0:
				tab.setName(repaymentEnum.getName());
				tab.setType(repaymentEnum.getValue());
				//op不传经销商id
				tab.setCount(orderScheduleService.getOrderScheduleCurrentPeriodCount(0));
				break;
			case 1:
				tab.setName(repaymentEnum.getName());
				tab.setType(repaymentEnum.getValue());
				//op不传经销商id
				tab.setCount(orderScheduleService.getOrderScheduleOverdueCount(0));
				break;
			case 2:
				tab.setName(repaymentEnum.getName());
				tab.setType(repaymentEnum.getValue());
				tab.setCount(offlineService.getOfflineCount(OfflineRepayTypeEnum.DEALER.getValue()));
				break;
			default:
				break;
			}
			tabList.add(tab);
		}
		return tabList;
	}

	/**
	 * 获取线下支付流水信息
	 * 
	 * @param offlineId
	 *            线下支付id
	 * @return
	 * @throws Exception
	 */
	@Override
	public PaymentOfflineVo getPaymentOfflineFlow(Integer offlineId) throws Exception {
		PaymentOfflineVo result = null;

		OfflineDto offlineDto = offlineService.getOffline(offlineId);
		if (null == offlineDto) {
			throw new Exception("还款信息为空");
		}

		result = new PaymentOfflineVo();
		BeanUtils.copyProperties(offlineDto, result);

		if (offlineDto.getDealerId() != null) {
			// 获取经销商名称
			DealerDto dealerDto = dealerService.getDealerById(offlineDto.getDealerId());
			if (null == dealerDto) {
				throw new Exception("经销商信息为空");
			}
			result.setDealerName(dealerDto.getShortName());
		}
		result.setAuditStatusName(OfflineAuditStatusEnum.getName(offlineDto.getAuditStatus()));
		return result;
	}

	/**
	 * 获取线下支付订单排期信息
	 * 
	 * @param offlineId
	 *            线下支付id
	 * @param repayType
	 *            线下支付类型
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<PaymentOfflineScheduleVo> getPaymentOfflineSchedule(Integer offlineId, OfflineRepayTypeEnum repayType)
			throws Exception {
		if (OfflineRepayTypeEnum.DEALER.equals(repayType)) {
			return getDealerOrderPaymentOfflineSchedule(offlineId);
		} else if (OfflineRepayTypeEnum.USER.equals(repayType)) {
			return getUserOrderPaymentOfflineSchedule(offlineId);
		} else {
			return null;
		}
	}

	/**
	 * 获取c端用户专属里程订单线下还款排期
	 * 
	 * @param offlineId
	 *            线下支付id
	 * @return
	 */
	private List<PaymentOfflineScheduleVo> getUserOrderPaymentOfflineSchedule(Integer offlineId) {
		List<PaymentOfflineScheduleVo> result = null;

		// 根据线下支付id获取订单排期id集合
		List<Integer> ids = offlineOrdersService.getScheduleIdList(offlineId);
		if (null == ids || ids.isEmpty()) {
			return result;
		}
		List<OrderScheduleOfflineBizDto> orderScheduleOfflineBizDtoList = orderScheduleBizService
				.getOrderScheduleOffline(ids);
		if (orderScheduleOfflineBizDtoList == null || orderScheduleOfflineBizDtoList.isEmpty()) {
			return result;
		}

		result = new ArrayList<>();
		// 用户id集合
		List<Integer> userIds = new ArrayList<>();
		// 车辆id集合
		List<Integer> carIds = new ArrayList<>();
		for (OrderScheduleOfflineBizDto orderScheduleOfflineBizDto : orderScheduleOfflineBizDtoList) {
			PaymentOfflineScheduleVo orderScheduleOfflineVo = Convert.toOrderScheduleOfflineVo(orderScheduleOfflineBizDto);

			userIds.add(orderScheduleOfflineBizDto.getUserId());
			carIds.add(orderScheduleOfflineBizDto.getCarId());

			result.add(orderScheduleOfflineVo);
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);
		// 查询车辆
		Map<Integer, CarDto> carMap = carService.getCarByIds(carIds);
		if ((userMap == null || userMap.isEmpty()) && (carMap == null || carMap.isEmpty())) {
			return result;
		}

		for (PaymentOfflineScheduleVo orderScheduleOfflineVo : result) {
			// 用户
			UserDto userDto = userMap == null ? null
					: userMap.isEmpty() ? null : userMap.get(orderScheduleOfflineVo.getUserId());
			// 用户手机号
			orderScheduleOfflineVo.setUserPhone(userDto == null ? null : userDto.getPhone());
			// 用户姓名
			orderScheduleOfflineVo.setUserRealName(userDto == null ? null : userDto.getRealName());
			// 车辆
			CarDto carDto = carMap == null ? null
					: carMap.isEmpty() ? null : carMap.get(orderScheduleOfflineVo.getCarId());
			// 车架号
			orderScheduleOfflineVo.setVin(carDto == null ? null : carDto.getVin());
			// 车牌号
			orderScheduleOfflineVo.setLicencePlate(carDto == null ? null : carDto.getLicencePlate());
		}

		return result;
	}

	/**
	 * 获取经销商订单线下还款排期
	 * 
	 * @param offlineId
	 *            线下支付id
	 * @return
	 */
	private List<PaymentOfflineScheduleVo> getDealerOrderPaymentOfflineSchedule(Integer offlineId) throws Exception {
		List<PaymentOfflineScheduleVo> result = null;

		List<Integer> ids = offlineOrdersService.getScheduleIdList(offlineId);
		if (null == ids || ids.size() <= 0) {
			throw new Exception("还款信息id为空");
		}

		List<OrderScheduleDetailBizDto> orderScheduleDetailBizDtoList = orderScheduleBizService
				.getOrderScheduleDetailBizDtoById(ids);
		if (null == orderScheduleDetailBizDtoList || orderScheduleDetailBizDtoList.size() <= 0) {
			throw new Exception("还款信息为空");
		}
		result = new ArrayList<>();
		PaymentOfflineScheduleVo offlineScheduleVo = null;
		for (OrderScheduleDetailBizDto orderScheduleDetailBizDto : orderScheduleDetailBizDtoList) {
			offlineScheduleVo = new PaymentOfflineScheduleVo();
			BeanUtils.copyProperties(orderScheduleDetailBizDto, offlineScheduleVo);
			DealerDetailDto dealerDetailDto = dealerDetailService
					.getDealerDetailById(orderScheduleDetailBizDto.getDealerId());
			if (null == dealerDetailDto) {
				throw new Exception("无联系人信息");
			}
			offlineScheduleVo.setContact(dealerDetailDto.getResponsibleName());
			offlineScheduleVo.setContactNumber(dealerDetailDto.getResponsiblePhone());

			result.add(offlineScheduleVo);
		}

		return result;
	}

	/**
	 * 获取线下支付审核信息
	 * 
	 * @param offlineId
	 *            线下支付id
	 * @return
	 * @throws Exception
	 */
	@Override
	public PaymentOfflineAuditVo getPaymentOfflineAudit(Integer offlineId) throws Exception {
		PaymentOfflineAuditVo result = null;
		OfflineAuditDto offlineAuditDto = offlineService.getOfflineAudit(offlineId);
		if (null == offlineAuditDto) {
			throw new Exception("审核信息为空");
		}
		result = new PaymentOfflineAuditVo();
		BeanUtils.copyProperties(offlineAuditDto, result);
		result.setAuditStatusStr(OfflineAuditStatusEnum.getName(offlineAuditDto.getAuditStatus()));
		return result;
	}

	/**
	 * 线下支付流水编号是否存在
	 * 
	 * @param serialNumber
	 *            流水编号
	 * @return
	 */
	@Override
	public Boolean getSerialNumberExists(String serialNumber) throws IllegalArgumentException, Exception {
		return offlineService.getSerialNumberExists(serialNumber);
	}

	/**
	 * 经销商订单支付未还款排期
	 * 
	 * @param orderCode
	 *            订单号
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<OrderScheduleRelationVo> getOrderScheduleRelationBizDto(Long orderCode)
			throws Exception {
		List<OrderScheduleRelationVo> orderScheduleRelationVoList = null;
		List<OrderScheduleRelationBizDto> orderScheduleRelationBizDtoList = orderScheduleBizService
				.getOrderScheduleRelationBizDto(orderCode);
		if (null == orderScheduleRelationBizDtoList || orderScheduleRelationBizDtoList.size() <= 0) {
			throw new Exception("非法入参");
		}
		orderScheduleRelationVoList = new ArrayList<>();
		OrderScheduleRelationVo orderScheduleRelationVo = null;
		for (OrderScheduleRelationBizDto orderScheduleRelationBizDto : orderScheduleRelationBizDtoList) {
			orderScheduleRelationVo = new OrderScheduleRelationVo();
			BeanUtils.copyProperties(orderScheduleRelationBizDto, orderScheduleRelationVo);
			orderScheduleRelationVoList.add(orderScheduleRelationVo);

		}

		return orderScheduleRelationVoList;
	}

	/**
	 * 用户订单支付未还款排期
	 * 
	 * @param orderCode
	 *            订单号
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<OrderRepaymentDetailVo> getOrderUserScheduleNoRepay(Long orderCode) throws Exception {
		List<OrderRepaymentDetailVo> result = null;

		// 查询订单未还款排期
		List<OrderScheduleDto> orderScheduleDtoList = orderScheduleService.getOrderSchedule(orderCode,
				OrderScheduleStatusEnum.NO);
		if (orderScheduleDtoList == null || orderScheduleDtoList.isEmpty()) {
			return result;
		}

		result = new ArrayList<>();
		for (OrderScheduleDto orderScheduleDto : orderScheduleDtoList) {
			OrderRepaymentDetailVo orderRepaymentDetailVo = Convert.toOrderRepaymentDetailVo(orderScheduleDto);
			orderRepaymentDetailVo.setPeriodsStr(orderScheduleDto.getPeriods() + "期");
			result.add(orderRepaymentDetailVo);
		}

		return result;
	}

	/**
	 * 线下支付查询未还款排期
	 * 
	 * @param orderCode
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<OrderRepaymentDetailVo> getOrderUserScheduleNoRepayOffline(Long orderCode) throws Exception {
		List<OrderRepaymentDetailVo> result = null;
		// 是否是专属订单
		OrderDto orderDto = orderService.getOrder(orderCode);
		if (orderDto == null) {
			// 不存在订单信息
			throw new BizException("订单编号错误");
		} else if (!OrderTypeEnum.EXCLUSIVEL.equals(orderDto.getType())) {
			throw new BizException("订单编号错误");
		}
		
		// 查询是否已经存在未审核线下还款
		if (offlineBizService.getUnAudit(orderCode)) {
			// 存在，提示返回
			throw new BizException("该订单有线下还款在审核中，暂时不能提交");
		}

		// 查询订单未还款排期
		List<OrderScheduleDto> orderScheduleDtoList = orderScheduleService.getOrderSchedule(orderCode,
				OrderScheduleStatusEnum.NO);
		if (orderScheduleDtoList == null || orderScheduleDtoList.isEmpty()) {
			throw new BizException("该订单已结清还款");
		}

		result = new ArrayList<>();
		for (OrderScheduleDto orderScheduleDto : orderScheduleDtoList) {
			OrderRepaymentDetailVo orderRepaymentDetailVo = Convert.toOrderRepaymentDetailVo(orderScheduleDto);
			orderRepaymentDetailVo.setPeriodsStr(orderScheduleDto.getPeriods() + "期");
			result.add(orderRepaymentDetailVo);
		}

		return result;
	}

	/**
	 * 订单线下支付新增
	 * 
	 * @param createVo
	 * @return
	 * @throws Exception
	 */
	@Override
	public Boolean createOrderPaymentOffline(PaymentOfflineCreateVo createVo) throws BizException, Exception {
		boolean result = true;

		// 验证流水编号是否存在
		if (offlineService.getSerialNumberExists(createVo.getSerialNumber())) {
			logger.error("流水编号(" + createVo.getSerialNumber() + ")已存在");
			throw new BizException(ResponseCodeEnum.PARMS_ERROR.getCode(), "新增失败，流水编号已存在");
		}

		// TODO 数据校验（校验排期是否已支付）

		// 数据转换
		OfflineBizCreateDto createDto = Convert.toOfflineBizCreateDto(createVo);

		//查询账号是否存在
		UserEntity currentLoginUser = tokenUtil.getUser();
		if(null == currentLoginUser){
			throw new Exception("用户未登录");
		}

		// 判断线下支付还款类型类型
		if (createVo.getDealerId() != null) {
			//校验如果订单有待审核的还款信息则不让通过

			//订单号去重
			List<PaymentOfflineScheduleCreateVo> uniqueOrderCode = createVo.getOfflineOrdersList().stream().collect(
					Collectors.collectingAndThen(
							Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PaymentOfflineScheduleCreateVo::getOrderCode))), ArrayList::new)
			);
			for (PaymentOfflineScheduleCreateVo paymentOfflineScheduleCreateVo:uniqueOrderCode) {
				List<OrderScheduleDto> orderScheduleDtoList = orderScheduleService.getOrderSchedule(paymentOfflineScheduleCreateVo.getOrderCode());
				for (OrderScheduleDto orderScheduleDto:orderScheduleDtoList) {
					if(OrderScheduleStatusEnum.TRADE_UNAUDIT.equals(orderScheduleDto.getStatus())){
						throw new BizException(ResponseCodeEnum.UNKNOWN_ERROR.getCode(),"订单号："+paymentOfflineScheduleCreateVo.getOrderCode()+"有待审核的还款记录");
					}
				}
			}

			// 经销商线下支付还款类型
			createDealerOrderPaymentOffline(createDto,currentLoginUser);
		} else {
			// 用户线下支付还款类型
			createUserOrderPaymentOffline(createDto);
		}

		List<String> emails = null;
		//邮件
		emails = getEmail(RiskEmailTypeEnum.ORDER_DEALER_REPAYMENT_REMINDER); // getRiskEmailList(RiskEmailEnum.ONE.getValue());
		if(null != emails){
			EmailUtil.sendMail(EMAIL_ACCOUNT, EMAIL_PASSWORD,
					EmailSubjectEnum.OFFLINE_PAYMENT_APPLY.getName(),
					EmailTemplateEnum.OFFLINE_PAYMENT_APPLY.getTemplate()
							.replace("$【name】", currentLoginUser.getRealName())
							.replace("$【serialNumber】", createVo.getSerialNumber()),
					emails);
		}else{
			logger.error("拒收车辆 未配置发送邮件人员的邮箱信息");
		}


		// 钉钉
		DingTalkUtil.execute( ORDER_REPAYMENT_CHECK_URL,
				EmailTemplateEnum.OFFLINE_PAYMENT_APPLY.getTemplate()
						.replace("$【name】", currentLoginUser.getRealName())
						.replace("$【serialNumber】", createVo.getSerialNumber()));

		return result;

	}

	/**
	 * 用户订单线下支付新增
	 * 
	 * @param createVo
	 * @throws Exception
	 */
	private boolean createUserOrderPaymentOffline(OfflineBizCreateDto createDto) throws Exception {
		boolean result = true;
		// 还款类型-用户
		createDto.setRepayType(OfflineRepayTypeEnum.USER.getValue());
		// 新增线下支付
		result = offlineBizService.createOffline(createDto);

		return result;
	}

	/**
	 * 经销商订单线下支付新增
	 * 
	 * @param createVo
	 * @throws Exception
	 */
	private boolean createDealerOrderPaymentOffline(OfflineBizCreateDto createDto,UserEntity currentLoginUser) throws Exception {

		boolean result = true;
		// 还款类型-经销商
		createDto.setRepayType(OfflineRepayTypeEnum.DEALER.getValue());
		createDto.setApplyId(currentLoginUser.getAccountId());
		createDto.setApplyName(currentLoginUser.getRealName());
		createDto.setApplyTime(LocalDateTime.now());
		// 新增线下支付
		result = offlineBizService.createOffline(createDto);

		if (result) {
			// 新增成功
			for (OfflineOrdersBizCreateDto scheduleCreateDto : createDto.getOfflineOrdersList()) {
				int ret = orderScheduleService.modifyStatusByIdAndOrderCode(scheduleCreateDto.getScheduleId(),OrderScheduleStatusEnum.TRADE_UNAUDIT.getValue(), null);
				if(ret <= 0){
					throw new Exception("修改失败");
				}
				OrderScheduleDto orderScheduleDto = orderScheduleService.getOrderSchedule(scheduleCreateDto.getScheduleId());
				// 如果是第一期则变更采购单主状态未已付首付款
				if (1 == orderScheduleDto.getPeriods()) {
					Boolean modifyOrderStatus = orderDealerService.modifyOrderStatus(scheduleCreateDto.getOrderCode(),
							OrderDealerStatusEnum.DOWN_PAYMENT_PAID.getValue());
					OrderStatusFlowCreateDto orderStatusFlowCreateDto = new OrderStatusFlowCreateDto();
					orderStatusFlowCreateDto.setOrderCode(scheduleCreateDto.getOrderCode());
					orderStatusFlowCreateDto.setOrderStatus(OrderDealerStatusEnum.DOWN_PAYMENT_PAID.getValue());
					//获取登录用户信息  操作人id，操作人名称，操作人类型，
					orderStatusFlowCreateDto.setOrderUserId(currentLoginUser.getAccountId());
					orderStatusFlowCreateDto.setOrderModifiedType(currentLoginUser.getSystemType().getValue());
					orderStatusFlowCreateDto.setOrderUserName(currentLoginUser.getRealName());
					// 订单流转状态插入
					Boolean createOrderStatusFlow = orderStatusFlowService
							.createOrderStatusFlow(orderStatusFlowCreateDto);
					if (!modifyOrderStatus || !createOrderStatusFlow) {
						return false;
					}
				}
			}
		}

		return result;
	}

	/**
	 * 获取邮件人信息
	 * @return
	 */
	private List<String> getEmail(RiskEmailTypeEnum riskEmailTypeEnum){
		List<RiskEmailDto> riskList = riskEmailService.getByType(riskEmailTypeEnum.getValue(),RiskEmailReceiveTypeEnum.EMAIL_RECIPIENT.getValue());
		List<String> list=null;
		if(null != riskList && !riskList.isEmpty()) {
			list=new ArrayList<>();
			for (RiskEmailDto dto : riskList) {
				list.add(dto.getEmail());
			}
		}
		return list;
	}

}
